class LinkListQueue<T> {
    class Node<T>(val e: T) {
        var next: Node<T>? = null

        override fun toString(): String {
            return "Node: $e"
        }
    }

    private var head: Node<T>? = null
    private var tail: Node<T>? = null
    private var size: Int = 0

    fun isEmpty(): Boolean {
        return  this.size == 0
    }

    fun getSize(): Int {
        return  this.size
    }

    fun enqueue(element: T) {
        val node = Node<T>(element)
        if (isEmpty()) {
            this.head = node
            this.tail = node

        }else {
            this.tail?.next = node
            this.tail = node
        }
        this.size += 1
    }

    fun dequeue(): T? {
        return if (isEmpty()) {
            null
        }else if (getSize() == 1) {
            val returnNode = this.head
            this.head = null
            this.tail = null
            this.size -= 1
            returnNode?.e
        }else {
            val returnNode = this.head
            this.head = returnNode?.next
            returnNode?.next = null
            this.size -= 1
            returnNode?.e
        }
    }

    override fun toString(): String {
        var description = "Queue: ["
        var cur = this.head
        while (cur != null) {
            description += "${cur.e} -> "
            cur = cur.next
        }

        return description + "null]"
    }
}
